using AutoMapper;
using B.S.XZYData.Api.Read.Application.Command.DefectiveSummary;
using B.S.XZYData.Api.Read.DTO;
using B.S.XZYData.ErrorCode;
using B.S.XZYData.Infrastructure;
using MediatR;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using B.S.XZYData.Domain.ZSH;

namespace B.S.XZYData.Api.Read.Application.Handler.DefectiveSummary
{
    /// <summary>
    /// 获取不良品汇总处理器
    /// </summary>
    public class GetDefectiveSummaryHandler : IRequestHandler<GetDefectiveSummaryCommand, ApiPageing<DefectiveSummaryDto>>
    {
        private readonly MyDbContext _dbContext;

        public GetDefectiveSummaryHandler(MyDbContext dbContext)
        {
            _dbContext = dbContext;
        }

        /// <summary>
        /// 应用排序
        /// </summary>
        private ISugarQueryable<B.S.XZYData.Domain.ZSH.WorkReport> ApplySort(
            ISugarQueryable<B.S.XZYData.Domain.ZSH.WorkReport> query, 
            string? sortField, 
            string? sortOrder)
        {
            if (string.IsNullOrEmpty(sortField))
            {
                // 默认按开始时间降序排序
                return query.OrderBy(wr => wr.StartTime, OrderByType.Desc);
            }

            var isDescending = !string.IsNullOrEmpty(sortOrder) && sortOrder.ToLower() == "desc";
            var orderType = isDescending ? OrderByType.Desc : OrderByType.Asc;

            switch (sortField.ToLower())
            {
                case "id":
                    return query.OrderBy(wr => wr.Id, orderType);
                case "workordercode":
                    return query.OrderBy(wr => wr.WorkOrderCode, orderType);
                case "productcode":
                    return query.OrderBy(wr => wr.ProductCode, orderType);
                case "productname":
                    return query.OrderBy(wr => wr.ProductName, orderType);
                case "processname":
                    return query.OrderBy(wr => wr.ProcessName, orderType);
                case "producer":
                    return query.OrderBy(wr => wr.Producer, orderType);
                case "productionstarttime":
                    return query.OrderBy(wr => wr.StartTime, orderType);
                case "productionendtime":
                    return query.OrderBy(wr => wr.EndTime, orderType);
                case "reportquantity":
                    return query.OrderBy(wr => wr.ReportQty, orderType);
                case "qualifiedquantity":
                    return query.OrderBy(wr => wr.GoodQty, orderType);
                case "defectivequantity":
                    return query.OrderBy(wr => wr.DefectiveQty, orderType);
                case "defectiverate":
                    // 不良率需要计算，使用表达式排序
                    if (isDescending)
                        return query.OrderBy("CASE WHEN ReportQty = 0 THEN 0 ELSE CAST(DefectiveQty AS DECIMAL) / ReportQty END DESC");
                    else
                        return query.OrderBy("CASE WHEN ReportQty = 0 THEN 0 ELSE CAST(DefectiveQty AS DECIMAL) / ReportQty END ASC");
                default:
                    // 无效的排序字段，使用默认排序
                    return query.OrderBy(wr => wr.StartTime, OrderByType.Desc);
            }
        }

        public async Task<ApiPageing<DefectiveSummaryDto>> Handle(GetDefectiveSummaryCommand request, CancellationToken cancellationToken)
        {
            // 先查询报工记录，然后通过Group获取汇总数据
            var query = _dbContext.WorkReport
                .Where(wr => !wr.IsDeleted)
                .WhereIF(!string.IsNullOrEmpty(request.WorkOrderCode), wr => wr.WorkOrderCode.Contains(request.WorkOrderCode!))
                .WhereIF(!string.IsNullOrEmpty(request.ProductCode), wr => wr.ProductCode.Contains(request.ProductCode!))
                .WhereIF(!string.IsNullOrEmpty(request.ProductName), wr => wr.ProductName.Contains(request.ProductName!))
                .WhereIF(!string.IsNullOrEmpty(request.ProcessName), wr => wr.ProcessName.Contains(request.ProcessName!))
                .WhereIF(!string.IsNullOrEmpty(request.Producer), wr => wr.Producer.Contains(request.Producer!))
                .WhereIF(request.ProductionStartTimeBegin.HasValue, wr => wr.StartTime >= request.ProductionStartTimeBegin!.Value)
                .WhereIF(request.ProductionStartTimeEnd.HasValue, wr => wr.StartTime <= request.ProductionStartTimeEnd!.Value)
                .WhereIF(request.ProductionEndTimeBegin.HasValue, wr => wr.EndTime >= request.ProductionEndTimeBegin!.Value)
                .WhereIF(request.ProductionEndTimeEnd.HasValue, wr => wr.EndTime <= request.ProductionEndTimeEnd!.Value)
                .WhereIF(request.ReportQuantityMin.HasValue, wr => wr.ReportQty >= request.ReportQuantityMin!.Value)
                .WhereIF(request.ReportQuantityMax.HasValue, wr => wr.ReportQty <= request.ReportQuantityMax!.Value)
                .WhereIF(request.QualifiedQuantityMin.HasValue, wr => wr.GoodQty >= request.QualifiedQuantityMin!.Value)
                .WhereIF(request.QualifiedQuantityMax.HasValue, wr => wr.GoodQty <= request.QualifiedQuantityMax!.Value);

            // 获取总数
            var totalCount = await query.CountAsync();
            
            // 计算总页数
            var totalPage = (int)Math.Ceiling((double)totalCount / request.Size);

            // 应用排序
            var orderedQuery = ApplySort(query, request.SortField, request.SortOrder);

            // 分页查询并转换为DTO
            var workReports = await orderedQuery
                .Skip((request.Index - 1) * request.Size)
                .Take(request.Size)
                .ToListAsync();

            // 获取对应的不良品明细
            var workReportIds = workReports.Select(wr => wr.Id).ToList();
            var defectiveItems = await _dbContext.WorkReportDefectiveItem
                .Where(di => workReportIds.Contains(di.WorkReportId) && !di.IsDeleted)
                .LeftJoin<Defective>((di, d) => di.DefectiveCode == d.DefectiveCode && !d.IsDeleted)
                .Select((di, d) => new { di.WorkReportId, DefectiveName = d.DefectiveName ?? di.DefectiveCode })
                .ToListAsync();

            // 转换为DTO
            var pageData = workReports.Select(wr => new DefectiveSummaryDto
            {
                Id = wr.Id,
                WorkOrderCode = wr.WorkOrderCode,
                ProductCode = wr.ProductCode,
                ProductName = wr.ProductName ?? "",
                ProcessCode = "", // 报工表中没有工序编号，如需要需要额外关联
                ProcessName = wr.ProcessName,
                Producer = wr.Producer,
                ProductionStartTime = wr.StartTime,
                ProductionEndTime = wr.EndTime,
                DefectiveItem = string.Join(",", defectiveItems.Where(di => di.WorkReportId == wr.Id).Select(di => di.DefectiveName)),
                ProcessPlanQuantity = 0, // 需要关联工单工序表获取
                ReportQuantity = wr.ReportQty,
                QualifiedQuantity = wr.GoodQty,
                DefectiveQuantity = wr.DefectiveQty,
                DefectiveRate = wr.ReportQty > 0 ? (decimal)wr.DefectiveQty / wr.ReportQty * 100 : 0,
                CreateTime = wr.StartTime // 使用报工开始时间作为创建时间
            }).ToList();

            return new ApiPageing<DefectiveSummaryDto>
            {
                Code = ApiEnum.Success,
                Msg = "查询成功",
                TotaCount = totalCount,
                TotaPage = totalPage,
                PageData = pageData
            };
        }
    }
} 